package com.naiterui.ehp.bs.doctor.dao.impl;

import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.google.common.collect.Lists;
import com.naiterui.common.repository.page.Page;
import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.ehp.bp.domain.Doctor;
import com.naiterui.ehp.bp.domain.NoticeInfo;
import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bs.doctor.dao.INoticeInfoDao;
import com.naiterui.ehp.bs.doctor.repository.INoticeInfoRepository;
import com.naiterui.ehp.bs.doctor.utils.RedisUtils;
import com.naiterui.ehp.bs.doctor.vo.CustomNoticeInfo;

@Repository
public class AdNoticeInfoDaoImpl implements INoticeInfoDao {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdNoticeInfoDaoImpl.class);

    @Autowired
    private EntityManager entityManager;

    @Autowired
    private INoticeInfoRepository noticeInfoRepository;

    @Override
    public NoticeInfo get(Long id) {
        return this.noticeInfoRepository.get(id);
    }

    /*
     * 获取用户可查看公告列表(无分页) INoticeInfoDao.getUserNotice()
     */
    @Override
    public List<NoticeInfo> getUserNotice(Date beginTime) {
        return this.noticeInfoRepository.findByStatusAndType(NoticeInfo.NOTICE_STATUS_EFFECTIVE
                , NoticeInfo.NOTICE_FLAG_NOT_DELETE);
    }

    /*
     * 获取用户可查看公告(处理用户删除标识) INoticeInfoDao.getNoticePage()
     */
    @Override
    public Page<CustomNoticeInfo> getNoticePage(PageParamVO pageParam, String limitTime, Long topic, Doctor doctor) {

        // 医生包含的标签ID列表(远程从CMS拿)
        //String drLabelIdStr = this.remoter.getDoctorLabelIdList(doctor.getId());
        String drLabelIdStr = null;
        Page<CustomNoticeInfo> result = null;

        // V2.3版本，前端左滑删除标识处理
        if (StringUtils.isNotEmpty(limitTime)) {
            // 获取用户未查看新公告数
            // String totalHql = "SELECT COUNT(DISTINCT ni.id) ";
            String totalHql = "SELECT COUNT(*) from (SELECT DISTINCT ni.id,ni.start_time as startTime,ni.topic_id AS topicId,"
                    + CustomNoticeInfo.TABLE_TYPE_CMS + " AS tableType ";
            totalHql += this.genBaseQuerySql(doctor, drLabelIdStr);
            String limitHql = totalHql;
            limitHql = limitHql + " AND alias.startTime > '" + limitTime + "' ";
            if (null != topic) {
                totalHql = totalHql + " AND alias.topicId = " + topic;
                limitHql = limitHql + " AND alias.topicId = " + topic;
            }
            // Long limitCount = getCount(limitHql, new Object[] {});
            // Long totalCount = getCount(totalHql, new Object[] {});
            Long limitCount = this.getCount(limitHql);
            Long totalCount = this.getCount(totalHql);
            if (limitCount < pageParam.getNum() && limitCount.compareTo(totalCount) != 0) {
                // 用户未看公告数小于分页数（第一页返回实际条数）
                result = this.genNoticePage(pageParam, limitTime, topic, doctor, drLabelIdStr);
                result.setTotalCount((int) (totalCount + pageParam.getNum() - limitCount));
            } else {
                // 用户未看公告数大于分页数（不处理）
                result = this.genNoticePage(pageParam, null, topic, doctor, drLabelIdStr);
            }
        } else {
            result = this.genNoticePage(pageParam, null, topic, doctor, drLabelIdStr);
        }

        return result;
    }

    private Page<CustomNoticeInfo> genNoticePage(PageParamVO pageParam, String limitTime, Long topic, Doctor doctor, String drLabelIdStr) {

        Page<CustomNoticeInfo> resultPage = Page.buildPage(pageParam.getPage(), pageParam.getNum(), Lists.newArrayList(), 0L);
        Map<String, Type> scalarMap = new HashMap<>();
        scalarMap.put("id", StandardBasicTypes.LONG);
        scalarMap.put("startTime", StandardBasicTypes.DATE);
        scalarMap.put("topicId", StandardBasicTypes.LONG);
        scalarMap.put("tableType", StandardBasicTypes.INTEGER);
        // String queryHql = " SELECT alias.* FROM (SELECT DISTINCT ni.* ";
        String queryHql = " SELECT alias.* FROM ( SELECT DISTINCT ni.id,ni.start_time as startTime,ni.topic_id as topicId,"
                + CustomNoticeInfo.TABLE_TYPE_CMS + " as tableType ";
        queryHql += this.genBaseQuerySql(doctor, drLabelIdStr);
        // 公告主题
        if (null != topic) {
            queryHql = queryHql + " AND alias.topicId = " + topic;
        }

        if (StringUtils.isNotEmpty(limitTime)) {

            // 处理用户删除标识
            int queryPage = pageParam.getPage();
            if (queryPage <= 1) {
                // 若为第一页，返回实际未看对象
                queryHql = queryHql + " AND alias.startTime > '" + limitTime + "' ";
            } else {
                // 若非第一页，返回limitId后正常分页对象
                queryHql = queryHql + " AND alias.startTime <= '" + limitTime + "' ";
                queryPage -= 1;
            }
            // 处理排序
            queryHql += " ORDER BY alias.startTime DESC ";

        } else {

            // 处理排序
            queryHql += " ORDER BY alias.startTime DESC  ";
        }

        String countSql = "select count(1) from (" + queryHql + ")";
        Query countQuery = this.entityManager.createNativeQuery(countSql);
        Long totalCount = (Long) countQuery.getSingleResult();
        resultPage.setTotalCount(totalCount);

        Query query = this.entityManager.createNativeQuery(queryHql, CustomNoticeInfo.class);
        query.setFirstResult(resultPage.getFirst()).setMaxResults(pageParam.getNum());
        List<CustomNoticeInfo> list = query.getResultList();
        resultPage.setResult(list);

        return resultPage;
    }

    private String genBaseQuerySql(Doctor doctor, String drLabelIdStr) {
        // 本方法为临时实现，节后统一规划修改
        Set<String> noticeIdSet = RedisUtils.smember("get_noticeIds_by_doctorId_" + doctor.getId());
        String noticeIdStr = this.toString(noticeIdSet);

        LOGGER.info("根据医生id=" + doctor.getId() + ", 获取所有的公告id=" + noticeIdStr);

        StringBuilder querySb = new StringBuilder(" FROM cms_notice_info ni LEFT JOIN cms_notice_label nl ON ni.id=nl.notice_id WHERE 1=1 ");
        // is_label = 0 非分层公告
        querySb.append(" AND ( ni.is_label=0 ");
        if (!StringUtils.isEmpty(drLabelIdStr)) {
            querySb.append("  or nl.label_id in (" + drLabelIdStr + ") ");
        }

        if (StringUtils.isNotEmpty(noticeIdStr)) {
            querySb.append(" OR ni.id in (" + noticeIdStr + ") ");
        }
        querySb.append(" ) ");
        querySb.append(" AND ni.type = " + NoticeInfo.NOTICE_FLAG_NOT_DELETE + " ");
        querySb.append(" AND ni.status IN (" + NoticeInfo.NOTICE_STATUS_EFFECTIVE + "," + NoticeInfo.NOTICE_STATUS_INVALID + ","
                               + NoticeInfo.NOTICE_STATUS_STOP + ") ");
        // querySb.append(" AND ni.start_time > '2017-12-01 00:00:00'");
        querySb.append(" AND ni.end_time >= '" + DateUtil.formatDate(doctor.getCreatedAt(), DateUtil.DATE_TIME_FORMAT) + "' ");
        // 自定义公告
        querySb.append(" UNION ALL ");
        querySb.append(" SELECT id,start_time AS startTime,topic_id AS topicId," + CustomNoticeInfo.TABLE_TYPE_DR
                               + " as tableType from dr_notice_info WHERE doctor_id=" + doctor.getId() + " AND status=" + 2);
        querySb.append(" )as alias ");
        querySb.append(" where 1=1  ");
        return querySb.toString();
    }

    private Long getCount(String sql) {
        Query query = this.entityManager.createNativeQuery(sql);

        List list = query.getResultList();
        if (list == null || list.isEmpty()) {
            return 0L;
        }
        if (null != list.get(0)) {
            BigInteger value = (BigInteger) (list.get(0));
            if (value != null) {
                return value.longValue();
            }
        }
        return 0L;
    }

    private String toString(Set<String> strings) {
        if (strings != null && strings.size() > 0) {
            StringBuilder sb = new StringBuilder();
            for (String str : strings) {
                if (sb.length() != 0) {
                    sb.append(",");
                }
                sb.append(str);
            }
            return sb.toString();
        }
        return "";
    }

    @Override
    public Map<Long, NoticeInfo> getNoticeInfoByList(List<Long> list) {
        Map<Long, NoticeInfo> map = new HashMap<>();
        if (list != null && !list.isEmpty()) {
            List<NoticeInfo> returnLis = this.noticeInfoRepository.findByIdIn(list);
            if (returnLis != null && !returnLis.isEmpty()) {
                for (NoticeInfo info : returnLis) {
                    map.put(info.getId(), info);
                }
            }
        }

        return map;
    }

    @Override
    public NoticeInfo getLateNoticeInfo(Doctor doctor, Long topic) {
        // 医生标签
        //String drLabelIdStr = this.remoter.getDoctorLabelIdList(doctor.getId());
        String drLabelIdStr = null;
        // 医生-公告关系
        Set<String> noticeIdSet = RedisUtils.smember("get_noticeIds_by_doctorId_" + doctor.getId());
        String noticeIdStr = this.toString(noticeIdSet);
        LOGGER.info("根据医生id=" + doctor.getId() + ", 获取所有的公告id=" + noticeIdStr);

        //StringBuilder querySb = new StringBuilder("select alias.* from (select ni.* FROM cms_notice_info ni LEFT JOIN cms_notice_label nl ON ni.id=nl.notice_id WHERE 1=1 ");
        StringBuilder querySb = new StringBuilder("select alias.* from (select ni.* FROM cms_notice_info ni WHERE 1=1 ");
        // is_label = 0 非分层公告
        //querySb.append(" AND ( ni.is_label=0 ");
        // 标签选择医生
        //if (!StringUtils.isEmpty(drLabelIdStr)) {
        //    querySb.append("  or nl.label_id in (" + drLabelIdStr + ") ");
        //}
        // 医生id选择医生
        //if (StringUtils.isNotEmpty(noticeIdStr)) {
        //    querySb.append(" OR ni.id in (" + noticeIdStr + ") ");
        //}
        //querySb.append(" ) ");
        // 公告主题
        if (null != topic) {
            querySb.append(" AND ni.topic_id = " + topic);
        }
        // 删除标识
        querySb.append(" AND ni.type = " + NoticeInfo.NOTICE_FLAG_NOT_DELETE + " ");
        // 公告状态
        querySb.append(" AND ni.status IN (" + NoticeInfo.NOTICE_STATUS_EFFECTIVE + "," + NoticeInfo.NOTICE_STATUS_INVALID + ","
                               + NoticeInfo.NOTICE_STATUS_STOP + ") ");
        // 结束时间大于医生注册时间
        querySb.append(" AND ni.end_time >= '" + DateUtil.formatDate(doctor.getCreatedAt(), DateUtil.DATE_TIME_FORMAT) + "' ");
        // 查询最近一条
        querySb.append(" ORDER BY ni.start_time DESC  ");
        querySb.append(" LIMIT 0,1 ");
        // 加上别名，别名必需alias
        querySb.append(" )alias");
        Query query = this.entityManager.createNativeQuery(querySb.toString(), NoticeInfo.class);
        List<NoticeInfo> list = query.getResultList();
        if (list != null && !list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

}
